package net.yxsoft.controller.pc.sysmgt.common.interceptor;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.HashKit;
import com.jfinal.kit.StrKit;
import rapid.core.TResult;

import java.util.Arrays;
import java.util.Map;

public class SignInterceptor implements Interceptor {

  private static String appId = "2da1df777612415f87314a6acb15c222";
  private static String appSecret = "32BA6B42AF146A96B7CA4c571550B91E311c38C1iC4BABD938I8E2F012D4BE1AA1";

  /**
   * api 的有效时间，默认为 1 分钟
   */
  private static final long TIMEOUT = 1 * 60 * 1000;

  @Override
  public void intercept(Invocation inv) {

    Controller c = inv.getController();

    Map<String, String[]> params = c.getParaMap();

    if(null == params && params.size() == 0){
      inv.getController().renderJson(TResult.fail().set("msg", "参数异常。"));
      return;
    }

    String appId = params.get("appId")[0];
    String sign = params.get("_sign")[0];
    String sn = params.get("sn")[0];

    if (StrKit.isBlank(appId) || !appId.equals(appId)) {

      c.renderJson(TResult.fail().msg( "请注意请求参数是否正确。"));
      return;
    }
    if (StrKit.isBlank(sign)) {

      c.renderJson(TResult.fail().msg("请提交签名数据。"));
      return;
    }

    Long time = sn == null || "null".equals(sn) ? null : Long.valueOf(sn);
    if (time == null) {
      inv.getController().renderJson(TResult.fail().msg("请提交 timestamp 参数数据。"));
      return;
    }


    // 时间验证，可以防止重放攻击
    if (Math.abs(System.currentTimeMillis() - time) > TIMEOUT) {

      inv.getController().renderJson(TResult.fail().msg("请求超时，请重新请求。"));
      return;
    }

    String localSign = createLocalSign(params);
    if (sign.equals(localSign) == false) {
      inv.getController().renderJson(TResult.fail().msg("数据签名错误。"));
      return;
    }
    inv.invoke();
  }

  private String createLocalSign(Map<String, String[]> params) {

    String[] keys = params.keySet().toArray(new String[0]);
    Arrays.sort(keys);
    StringBuilder query = new StringBuilder();
    for (String key : keys) {
      if ("_sign".equals(key)) {
        continue;
      }

      String value = params.get(key)[0];
      query.append(key).append("=").append(value).append("&");
    }
    query.append(appSecret);
    return HashKit.md5(query.toString()).toUpperCase();
  }
}
